package combiner;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class SearchingWeight {
	
	public static String trainCombinePath = "/Users/macpro724/Desktop/ml_prj/data/netflix/download/combine/train_result.txt";
	public static String validationCombinePath = "/Users/macpro724/Desktop/ml_prj/data/netflix/download/combine/validation_result.txt";
	public static String testCombinePath = "/Users/macpro724/Desktop/ml_prj/data/netflix/download/combine/test_result.txt";
	
	public static String plotFilePath = "/Users/macpro724/Desktop/ml_prj/data/netflix/download/plot/searchWeigth.csv";
	
	public final int MAX_TRAINING = 99072113;
	public final int MAX_VALIDATION = 1408396;
	public final int MAX_TESTING = 2817132;
	
	public float[] rtrain_svd;
	public float[] rtrain_lnr;
	public float[] rtrain_ans;
	
	public float[] rtest_svd;
	public float[] rtest_lnr;
	public float[] rtest_ans;
	
	public float[] rvalid_svd;
	public float[] rvalid_lnr;
	public float[] rvalid_ans;
	
	public int trainIndex = 0;
	public int testIndex = 0;
	public int validIndex = 0;
	
	public SearchingWeight(){
		rtrain_svd = new float[MAX_TRAINING];
		rtrain_lnr = new float[MAX_TRAINING];
		rtrain_ans = new float[MAX_TRAINING];
		
		rtest_svd = new float[MAX_TESTING];
		rtest_lnr = new float[MAX_TESTING];
		rtest_ans = new float[MAX_TESTING];
		
		rvalid_svd = new float[MAX_VALIDATION];
		rvalid_lnr = new float[MAX_VALIDATION];
		rvalid_ans = new float[MAX_VALIDATION];
	}
	
	public int importData(float[] rating_svd, float[] rating_lnr, float[] rating_ans, String filePath){
		BufferedReader br;
		int index = 0;
		try{
			br = new BufferedReader(new FileReader(filePath));
			
			String line;
			
			while((line = br.readLine()) != null){
				String[] s = line.split(",");
				rating_svd[index] = Float.parseFloat(s[0]);
				rating_lnr[index] = Float.parseFloat(s[1]);
				rating_ans[index] = Float.parseFloat(s[2]);
				index++;
			}
			
			br.close();
		}catch(Exception e){
			e.printStackTrace();
		}
		return index;
	}
	
	public void searchWeight(){
		
		double sumWeight = 1;
		double svdWeight = sumWeight;
		double lnrWeight = 0;
		double lrate = 0.01;
		
		double rmse_train;
		double rmse_valid;
		double rmse_test;
		
		double score;
		double sq;
		double err;
		
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(SearchingWeight.plotFilePath));
			
			while (svdWeight > 0){
				
				//rmse for validation
				rmse_valid = 0;
				sq = 0;
				for (int i = 0; i < validIndex; i++){
					score = svdWeight*rvalid_svd[i] + lnrWeight*rvalid_lnr[i];
					score = normValue(score);
					err = score - rvalid_ans[i];
					sq += err*err;
				}
				rmse_valid = Math.sqrt(sq/validIndex);
				
				//rmse for validation
				rmse_test = 0;
				sq = 0;
				for (int i = 0; i < testIndex; i++){
					score = svdWeight*rtest_svd[i] + lnrWeight*rtest_lnr[i];
					score = normValue(score);
					err = score - rtest_ans[i];
					sq += err*err;
				}
				rmse_test = Math.sqrt(sq/testIndex);

				//rmse for validation
				rmse_train = 0;
				sq = 0;
				for (int i = 0; i < trainIndex; i++){
					score = svdWeight*rtrain_svd[i] + lnrWeight*rtrain_lnr[i];
					score = normValue(score);
					err = score - rtrain_ans[i];
					sq += err*err;
				}
				rmse_train = Math.sqrt(sq/trainIndex);

				bw.write("" + rmse_train + "," + rmse_valid + "," + rmse_test + "\n"); 
				System.out.println("" + rmse_train + "," + rmse_valid + "," + rmse_test + "\n");
				
				lnrWeight += lrate;
				svdWeight = sumWeight - lnrWeight;
				
			}
			
			bw.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		
	}
	
	public double normValue(double score){
		double temp = score;
		if (temp > 5) temp = 5;
		else if (temp < 1) temp = 1;
		return temp;
	}
	
	public static void main(String[] args){
		SearchingWeight engine = new SearchingWeight();
		System.out.println("After building!!");
		
		engine.testIndex = engine.importData(engine.rtest_svd, engine.rtest_lnr, engine.rtest_ans, testCombinePath);
		System.out.println("Imported test!!");
		
		engine.validIndex = engine.importData(engine.rvalid_svd, engine.rvalid_lnr, engine.rvalid_ans, validationCombinePath);
		System.out.println("Imported validatino!!");
		
		engine.trainIndex = engine.importData(engine.rtrain_svd, engine.rtrain_lnr, engine.rtrain_ans, trainCombinePath);
		System.out.println("Impored training!!");
		
		engine.searchWeight();
	}

}
